<?php

namespace Addons\CentralControl\Services;

use Common\BaseService;

class ModbusService extends BaseService
{
    /**
     * 输出工位指令
     * @param $stationNumber
     * @param $type
     * @return string
     */
    function buildModbusCommandNum($stationNumber,$type)
    {
        /**
         * 转16进制，并且占2个8字节
         */
        $stationNumber = intval($stationNumber);
        $stationNumber = str_pad(dechex($stationNumber), 4, '0', STR_PAD_LEFT);
        $stationNumber = str_split($stationNumber, 2);
        $stationNumber = array_map('hexdec', $stationNumber);
        // 固定格式
        $typeFormat = [0x01, 0xF6];//入口
        switch ($type) {
            case 1:
                $typeFormat = [0x01, 0xF6];//入口
                break;
            case 2:
                $typeFormat = [0x01, 0xF8];//出口
                break;
        }
        $fixedFormat = array_merge([0x01, 0x10],$typeFormat,[0x00, 0x04, 0x08]);
        // 实际数据
//        $data = array_merge($stationNumber, [0x00, 0x00]);
//        $data = array_merge($stationNumber, [0x00, 0x00]);
        $data = array_merge($stationNumber, [0x00, 0x1E, 0x00, 0x31, 0x00, 0x00]);

        // 合并所有数据
        $command = array_merge($fixedFormat, $data);

        $crc = $this->calculateCRC16Modbus($command);
        $crcLow = $crc & 0xFF;
        $crcHigh = ($crc >> 8) & 0xFF;
        $finalCommand = array_merge($command, [$crcLow, $crcHigh]);
        return implode('', array_map(function ($byte) {
            return sprintf('%02X', $byte);
        }, $finalCommand));
    }


    /**
     * 监听状态
     * @param $type
     * @return string
     */
    function buildModbusCommandStatus($type)
    {
        // 固定格式 01 03 01 F6 00 04 A5 C7
        //        503 入料口反馈
        //        505  出料口反馈
        switch ($type) {
            case 505:
                $typeFormat = [0x01, 0xF9];
                break;
            case 503:
            default:
                $typeFormat = [0x01, 0xF7];
                break;
        }
        $command = array_merge([0x01, 0x03],$typeFormat,[0x00, 0x04]);

        $crc = $this->calculateCRC16Modbus($command);
        $crcLow = $crc & 0xFF;
        $crcHigh = ($crc >> 8) & 0xFF;
        $finalCommand = array_merge($command, [$crcLow, $crcHigh]);
        return implode('', array_map(function ($byte) {
            return sprintf('%02X', $byte);
        }, $finalCommand));
    }

    // 计算CRC16/Modbus校验码
    function calculateCRC16Modbus($data): int
    {
        $crc = 0xFFFF; // 初始化CRC寄存器

        foreach ($data as $byte) {
            $crc ^= $byte; // 当前字节与CRC寄存器的低8位进行异或

            for ($j = 0; $j < 8; $j++) {
                if ($crc & 0x0001) { // 如果最低位为1
                    $crc = ($crc >> 1) ^ 0xA001; // 应用多项式0x8005 (0xA001是0x8005的反序)
                } else {
                    $crc >>= 1; // 右移一位
                }
            }
        }

        return $crc;
    }




}